package com.zdzx.common.config;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.alibaba.fastjson.JSON;
import com.zdzx.base.common.util.JwtUtil;
import com.zdzx.base.common.util.RedisUtil;
import com.zdzx.base.common.util.TokenInfo;
import com.zdzx.common.result.Result;
import com.zdzx.common.result.ResultCode;
import com.zdzx.common.result.ResultUtil;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;


public class AuthFilter extends HandlerInterceptorAdapter {

	//private final static String DEFAULT_FILTER_PATH = "/socket/test";
	@Autowired
  private RedisUtil redisUtil;

  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
    System.out.println(request.getRequestURI());
    if (checkURI(request.getRequestURI(), request.getMethod())) {
      return true;
    } else {
      String token;
      if(request.getRequestURI().contains("socket")) {
        token = request.getHeader("Sec-WebSocket-Protocol");
      }else {
        token = request.getHeader("Authorization");
      }
      System.out.println(request.getRequestURI());
      System.out.println("token:"+token);
      if (StringUtils.isNotBlank(token)) {
        Map<String, Object> checkJWT = JwtUtil.checkJWT(token);
        if ((boolean) checkJWT.get("result")) {
          // Jws<Claims> parseJWT
          Map<String, Object> parseJWT1 = JwtUtil
              .parseJWT(JwtUtil.generateKey(JwtUtil.JWT_ALG, JwtUtil.JWT_RULE), token);
          if (!(boolean) parseJWT1.get("result")) {
            String code = parseJWT1.get("code").toString();
            ResultCode valueOf = ResultCode.valueOf(code);
            returnJson(response,ResultUtil.data(valueOf.getCode(), valueOf.getMes(),null));
            return false;
          }

          @SuppressWarnings("unchecked")
          Jws<Claims> parseJWT = (Jws<Claims>) parseJWT1.get("code");
          String userId = parseJWT.getBody().getId();
          String subject = parseJWT.getBody().getSubject();
          String key=TokenInfo.getKey(userId,subject);
          boolean hasKey = redisUtil.hasKey(key);
          if (hasKey) {
            /*UserInfo userInfo = (UserInfo) redisUtil.get(key);
            if(!userInfo.getToken().equals(token)) {
              returnJson(response,ResultUtil.data(ResultCode.TOKEN_SIGNATURE.getCode(), ResultCode.TOKEN_SIGNATURE.getMes(), null));
              return false;
            }*/
            return true;

          } else {
            returnJson(response,ResultUtil.data(ResultCode.TOKEN_EXPIREDJWT.getCode(), ResultCode.TOKEN_EXPIREDJWT.getMes(), null));
            return false;
          }

        } else if(ResultCode.TOKEN_MALFORMEDJWT.equals(checkJWT.get("code").toString())){
          /* TokenInfo tokenInfo = JwtUtil.parseExpriToken(token);
          if (tokenInfo!=null) {
            String key = TokenInfo.getKey(tokenInfo.getId(),tokenInfo.getFrom());
            if(redisUtil.hasKey(key)) {
              returnJson(response,ResultUtil.data(ResultCode.TOKEN_SIGNATURE.getCode(), ResultCode.TOKEN_SIGNATURE.getMes(), null));
              return false;
            }
          }
          return true;*/
          returnJson(response,ResultUtil.data(ResultCode.TOKEN_MALFORMEDJWT.getCode(), ResultCode.TOKEN_MALFORMEDJWT.getMes(), null));
          return false;
        }else {
          String code = checkJWT.get("code").toString();
          ResultCode valueOf = ResultCode.valueOf(code);
          returnJson(response,ResultUtil.data(valueOf.getCode(), valueOf.getMes(), null));
          return false;
        }
      } else {
        returnJson(response,ResultUtil.data(ResultCode.TOKEN_NULL.getCode(), ResultCode.TOKEN_NULL.getMes(), null));
        return false;
      }

  }
      //return true;
  }
   
	private static boolean checkURI(String requestURI, String requestMethod) {

    requestURI = requestURI.replaceFirst("//","/");
    System.out.println("requestURI:"+requestURI);
//    requestURI = requestURI.replaceFirst("//","/");
		List<String> list = new ArrayList<String>();
		list.add("/admin/refToken");
		list.add("/admin/login");
		list.add("/web/refToken");
		list.add("/web/login");
		list.add("/web/imageCode");
		list.add("/web/sendMobile");
		list.add("/course/rescoure/*");
		list.add("/doc.html");
		list.add("/web/pv");
		list.add("/web/authFile");
		
		
		list.add("/admin/course/user/watchCourse/export");
		
		
		//list.add("/socket/test/*");
		
		//list.add("/swagger-ui.html");
		//list.add("/v2/api-docs");
		//list.add("/");
		//list.add("/csrf");
		
		if(requestURI.contains("/swagger-ui.html")) {
			return true;
		}else if(requestURI.contains("/v2/api-docs")){
			return true;
		}
		if(requestURI.startsWith("/web/"))
			return true;
		if(requestURI.startsWith("/resouce/"))
			return true;
		if(requestURI.startsWith("/favicon.ico/"))
			return true;
		for (String string : list) {
			if (string.contains("*")) {
				string = string.replaceAll("\\*", "\\\\w*");
			} else if (requestURI.equals(string)) {
				return true;
			}
			if (Pattern.matches(string, requestURI)) {
				return true;
			}
		}
		return false;
	}
	
	private void returnJson(ServletResponse response,Result<T> result){
	    PrintWriter writer = null;
	    response.setCharacterEncoding("UTF-8");
	    response.setContentType("text/html; charset=utf-8");
	    try {
	        writer = response.getWriter();
	        writer.print(JSON.toJSONString(result));

	    } catch (IOException e) {
	        //log.error("response error",e);
	    } finally {
	        if (writer != null)
	            writer.close();
	    }
	}

}
